/**
 * 并发任务控制
 */

/**
 * 耗时函数
 * @param {number} time 时间
 * @returns {Promise<void>}
 */
function timeout(time) {
  return new Promise(resolve =>
    setTimeout(() => {
      resolve();
    }, time)
  );
}

/**
 * 并发控制器
 * @param {number} parallelCount 最大并发数
 * @param {Array} tasks 任务列表
 * @param {number} runningTaskCount 当前并发数
 */
class SuperTask {
  constructor(parallelCount = 2) {
    this.parallelCount = parallelCount;
    this.tasks = [];
    this.runningTaskCount = 0;
  }

  /**
   * 排队函数
   * @param {Function} task 任务
   * @returns {Promise<void>}
   */
  add(task) {
    return new Promise((resolve, reject) => {
      this.tasks.push({ task, resolve, reject });
      this.#run();
    });
  }

  /**
   * 取号执行函数
   */
  #run() {
    while (this.runningTaskCount < this.parallelCount && this.tasks.length) {
      const { task, resolve, reject } = this.tasks.shift();
      this.runningTaskCount++;
      Promise.resolve(task())
        .then(resolve, reject)
        .finally(() => {
          this.runningTaskCount--;
          this.#run();
        });
    }
  }
}

// 测试
const superTask = new SuperTask();
function addTask(time, name) {
  superTask
    .add(() => timeout(time))
    .then(() => {
      console.log(`任务${name}完成`);
    });
}

addTask(10000, 1); // 10000ms后输出：任务1完成
addTask(5000, 2); // 5000ms后输出：任务2完成
addTask(3000, 3); // 8000ms后输出：任务3完成
addTask(4000, 4); // 12000ms后输出：任务4完成
addTask(5000, 5); // 15000ms后输出：任务5完成

/* addTask(1000, 1);
addTask(1000, 2);
addTask(1000, 3);
addTask(1000, 4);
addTask(1000, 5); */
